#include "Buffer.h"

#include <sstream>
namespace frame {

Buffer::Buffer()
: position(0)
, limit(0)
, cap(kBufferLength)
{
    memset(buf, 0, kBufferLength);
}
Buffer::~Buffer(){
}

void * Buffer::buffer() const{
    return (void*)(limit + buf);
}
size_t Buffer::freeBytes() const{
    return cap - limit;
}

const void * Buffer::data() const {
    return (const void *)(buf + position);
}
size_t Buffer::inBytes() const {
    return limit - position;
}

// seek limit to next as put data in
size_t Buffer::fakePut(size_t bytes) {
    if(bytes >= 0){
        bytes = std::min(bytes, freeBytes());
        limit += bytes;
        return bytes;
    }
    return -1;
}
size_t Buffer::fakeGet(size_t bytes){
    if(bytes >= 0){
        bytes = std::min(bytes, inBytes());
        position += bytes;
        return bytes;
    }
    return -1;
}
void Buffer::compact(){
    size_t inbytes = inBytes();
    if(inbytes > 0){
        memmove(buf, buf + inbytes, inbytes);
        position = 0;
        limit = inbytes;
    }
}

int Buffer::putBytes(const char * data, size_t len){
    assert(data != NULL);
    if(len >= 0){
        len = std::min(len, freeBytes());
        memcpy(buffer(), data, len);
        limit += len;
        return len;
    }
    return -1;
}
int Buffer::getBytes(char * data, size_t len){
    assert(data != NULL);
    if(len >= 0){
        len = std::min(len, inBytes());
        memcpy(data, this->data(), len);
        position += len;
        return len;	
    }
    return -1;
}
std::string Buffer::toString() const {
    std::ostringstream oss;
    oss << " readBuffer:[pos:" << position 
        << ", limit:" << limit  << "]" ;
    return oss.str();
}

} // end of namespace frame
